package cn.mayday.algorithms.year2021.month1.E栈专题;

import java.util.Stack;

/**
 * 输入一个链表的头节点，从尾到头反过来返回每个节点的值（用数组返回）。
 * <p>
 * <p>
 * <p>
 * 示例 1：
 * <p>
 * 输入：head = [1,3,2]
 * 输出：[2,3,1]
 * <p>
 * 来源：力扣（LeetCode）
 * 链接：https://leetcode-cn.com/problems/cong-wei-dao-tou-da-yin-lian-biao-lcof
 * 著作权归领扣网络所有。商业转载请联系官方授权，非商业转载请注明出处。
 *
 * @author Mayday05
 * @date 2021/1/5 20:45
 */
public class Off06ReversePrint {

    public static void main(String[] args) {

        Off06ReversePrint print = new Off06ReversePrint();
        ListNode head1 = new ListNode(1);
        ListNode head2 = new ListNode(2);
        ListNode head3 = new ListNode(3);
        head3.next = null;
        head2.next = head3;
        head1.next = head2;

        int[] resultArray = print.reversePrint(head1);

        for (int temp : resultArray) {
            System.out.println(temp);
        }
    }

    // 方法一： 暴力循环，时间复杂度O(n)，空间复杂度O(n)
    public int[] reversePrint1(ListNode head) {

        int count = 0;
        ListNode temp = head;
        while (temp != null) {
            count++;
            temp = temp.next;
        }
        int[] result = new int[count]; //如果结果存储不算空间的话，确实没有使用辅助空间

        while (head != null && count >= 1) {
            result[count - 1] = head.val;
            head = head.next;
            count--;
        }
        return result;
    }

    // 方法2： 使用堆栈，充分利用栈的先进后出的特性
    // 其实并没有优化和方法1，时间复杂度O(n)，空间复杂度O(n)，这里能用栈的地方方法1使用数组的坐标也是一样的
    public int[] reversePrint(ListNode head) {
        Stack<Integer> stack = new Stack<Integer>();
        while (head != null) {
            stack.push(head.val);
            head = head.next;
        }

        int length = stack.size();
        int[] result = new int[length];
        for (int i = 0; i < length; i++) {
            result[i] = stack.pop();
        }
        return result;
    }

    // 方法3：使用递归



    public static class ListNode {
        int val;
        ListNode next;

        ListNode(int x) {
            val = x;
        }
    }
}
